import com.sun.xml.internal.ws.api.model.wsdl.WSDLOutput;

import java.lang.reflect.Array;
import java.util.Arrays;

public class Practice {
    public static void main2(String[] args) {
        Person person1 = new Person();
       // person1.play();
        Person.play();
    }

    public static void main1(String[] args) {
        // 数组的使命：是用来存储一组相同数据类型的数据的
        //数组的存储：向内存申请一片连续的空间，然后将空间划分
        //为我们申请的元素的个数，Java从0开始进行编号,将这个号码作为元素的下标。
        //数组的创建：
        //数组元素类型[] 数组名 = new 数组元素类型[]{};
        //数组元素类型[] 数组名 = {};
        //数组元素类型[] 数组名 = new 数组元素类型[10];
        //数组的创建一共有两种方式，在上面的代码中，第一行代码创建数组的方式和第二行一致
        //第二行创建数组的方式是第一行的简化版（由于数组在编程中应用范围广，所以Java语法简化了数组的创建方式）
        //相同的还有字符串的创建
        int[] array1 = new int[]{1,2,3,4,5,6};
        int[] array2 = {1,2,3,4,5,6};
        int[] array3 = new int[10];
        String str1 = new String("hello");
        String str2 = "hello";

        //这两种创建方式之间的区别是一旦初始化就不能指定数组大小，一旦指定大小就不能初始化
        //而没有初始化的数组内的元素都是默认值1
        //boolean 的默认值是false
        //数组的创建一旦分成两行写，就不能再进行简化了
        int[] array4;
        array4 = new int[10];

        int[] array5;
        array5 = new int[]{1,2,3,4,5,6};

        //数组的使用；数组通过下标引用数组元素
        //数组越界：在使用下标访问数组时，很有可能超出数组的存储空间,Java直接报错
        //取数组元素
        int[] array10 = {1,2,3,4,5,6,7,8,9,10};
        System.out.println(array10[10]);
        System.out.println(array10[-1]);

        //求数组长度
        System.out.println(array10.length);
        //修改数组元素数据
        array10[9] = 99;

        //遍历数组
//        一个一个元素遍历

        System.out.println(array10[0]);
        System.out.println(array10[1]);
        System.out.println(array10[2]);
//        for循环遍历数组-->通过下标访问
        for (int i = 0; i < array10.length; i++) {
//            array10[i] = i;
            System.out.println(array10[i]);
        }
//        foreach--》和下标无关
        for (int x : array10) {
            System.out.println(x);
        }
        //foreach相当于将每个数组元素数据赋值给x，foreach不能改变数组元素的值，只能进行遍历
//        for (数组元素类型 变量名:数组名 ) {
//
//        }
        Arrays.sort(array10);
    //arrays数组转字符串遍历数组
        System.out.println(Arrays.toString(array10));
    }
//            System.out.println(array10[-1]);

    public static void main5(String[] args) {
//数组是引用类型
        int[] array = new int[10];
    }
    //JVM（Java虚拟机）内存的划分：java虚拟机栈 本地方法栈 堆 方法区 程序计数器
    //平时所说的栈就是Java1虚拟机栈
    //局部变量存在Java栈上---》局部变量是在方法上定义的
    //引用变量：指向对象的变量，引用变量存储的是对象的地址
    //引用变量和局部变量无关，但是当引用变量在方法内创建时是局部变量
    //当引用变量不在方法内创建时就不是局部变量，所以引用变量和局部变量无关
    //只要是new出来的，必定存在堆上
    //array是一个引用变量，或者称引用，存储的是数组的地址

    //变量类型 基本数据类型（8） 引用变量（数组，字符串，其他）
    //是否是局部变量和变量的类型无关，只看变量是否创建在方法内部
    //任何类型的变量只要创建在方法内，就是局部变量
    public static void main6(String[] args) {
        //作业
        int[] array = new int[100];
        for (int i = 0; i < array.length; i++) {
            array[i] = i+1;
        }
        for (int x : array) {
            System.out.println(x);
        }
        System.out.println(Arrays.toString(array));
    }


    public static void main7(String[] args) {
        //基本数据类型
        //引用类型 ：引用变量，就是一个变量存地址

        //局部变量的内存就是在栈上开辟的
        //对象就是在堆上开辟的

        //局部变量就是在方法内部定义的变量，和引用变量无关，这
        //两个概念是不一样的，相互独立的

        //byte short int long float double char boolean
        //基本变量：基本数据类型创建的变量
        //引用变量并不直接存储对象本身，而是存储对象的地址
        //Java语法中，局部变量必须初始化后才能使用

//        int[] array;
//        System.out.println(array);
//        int a;
//        System.out.println(a);
        int[] array = null;
        //null说明引用不指向任何对象，所以在书写时，直接赋值null
        System.out.println(array);
        System.out.println(array[0]);
        //当赋值为null后，
    }

    //引用变量难点
    public static void main16(String[] args) {
        int[] array1 = {1,2,4,5};
        int[] array2 = {3,5,6,7};
        array2 = array1;
        System.out.println(Arrays.toString(array1));
        System.out.println(Arrays.toString(array2));
        array1[0] = 999;

        //两个引用指向同一个对象，通过其中一个引用去修改这个对象时，
        //另一个引用去访问时，访问到的对象也是被修改后的
        //当对象没有引用指向时，这个对象就会被系统自动回收
    }

    public static void main9(String[] args) {
        int[] arr1 = new int[3];
        arr1[0] = 10;
        arr1[1] = 20;
        arr1[2] = 20;
        int[] arr2 = new int[]{1,2,3,4,5};
        arr2[3] = 400;
        arr2[4] =500;

        arr1 = arr2;
        arr1[0] = 100;
        arr1[1] = 200;
        arr1[2] = 300;

        System.out.println(Arrays.toString(arr1));
        System.out.println(Arrays.toString(arr2));

        //C语言中1null是空指针，明确是有一个地址的，只是这个地址是受保护的，不能访问
        //而在Java中null说明不指向任何对象，不存地址


    }

    public static void main4(String[] args) {

    }

//数组的应用场景保存数据
//作为函数的参数--->传递的是引用变量存储的数据，则形参也会指向实参指向的对象
    public static void main12(String[] args) {
        int[] array = {1,2,3,4};
        func1(array);
        System.out.println(Arrays.toString(array));
        func2(array);
        System.out.println(Arrays.toString(array));
    }

    public static void func1(int[] array) {
        array = new int[]{15,16,17};
        //只是改变了形参的指向，并不会改变实参的指向（形参是实参的一份临时拷贝）

    }

    //传递引用，通过引用修改了原来的值
    public static void func2(int[] array) {
//        int[] array1 = {1,2,3,4};
        array[0] = 99;
        //通过形参指向实参的对象从而修改实参指向的对象
        //实参存储数据不变，改变的是实参指向的对象
    }

//总计，当数组作为参数进行传递的时候，其实还是按值传递，只不过此时的值是一个地址
//那么就会出现两种情况  第一个种情况--》形参修改指向   array = new int[]{1}
// 第二--》形参修改执行对象的值    array[0] = 100;

    //数组作为函数返回值返回
    public static int[] func10() {
        int[] array = {1,2,3,4,5};
        int[] tmp = {10,11,13};
        return array;
    }
    //将数组扩大二倍
    public static int[] grow(int[] arr) {
        for (int i = 0; i < arr.length; i++) {
            arr[i] = arr[i] * 2;
            //相当于是在同一个对象上进行了修改，没有必要返回
        }
        return arr;
    }

    public static void grow11(int[] arr) {
        for (int i = 0; i < arr.length; i++) {
            arr[i] = arr[i] * 2;
            //相当于是在同一个对象上进行了修改，没有必要返回
        }
    }

    public static int[] grow1(int[] arr) {
        int[] tmp = new int[arr.length];
        for (int i = 0; i < arr.length; i++) {
            tmp[i] = arr[i] * 2;
            //相当于是在同一个对象上进行了修改，没有必要返回
        }
        return tmp;
    }

    public static void main112(String[] args) {
        int[] arr = func10();
        int[] arr1 = {1,2,3,4,5,6,7,8};
        int[] tmp =  grow1(arr1);
        System.out.println(Arrays.toString(arr1));
        System.out.println(Arrays.toString(tmp));

        int[] tmp2 = grow(arr1);
        System.out.println(Arrays.toString(arr1));
        System.out.println(Arrays.toString(tmp2));
    }

    //练习
    public static void main114(String[] args) {
        int[] arr = {1,2,3,4};
        System.out.println(Arrays.toString(arr));
        System.out.println(myToString(arr));
        System.out.println(myToString(null));
  //      System.out.println(Arrays.toString(null));
    }
    public static String myToString(int[] arr) {
        //空指针的时候异常
        if(arr == null) {
            return "[null]";
        }
        String str = "[";
        for (int i = 0; i < arr.length; i++) {
            str = str + arr[i];
            if(i < arr.length - 1) {
                str = str + ",";
            }
        }
        str = str + "]";
        return str;
    }

    //数组拷贝
    public static int[] copy(int[] arr) {
        int[] c1 = new int[(arr.length) * 2];
        for (int i = 0; i < arr.length; i++) {
            c1[i] = arr[i];
        }
        return c1;
    }

    //copyof也可以当成扩容
    public static void main119(String[] args) {
        int[] arr = {1,2,3,4,5,6};
        //copyof 原数组 拷贝长度
        int[] ret = Arrays.copyOf(arr,arr.length);
        System.out.println(Arrays.toString(arr));
        System.out.println(Arrays.toString(ret));
    }
    //由native修饰的方法，底层是由c或cpp实现的，看不到具体实现
    public static void main120(String[] args){

        int[] arr = {1,2,3,4};
        int[] tmp = new int[arr.length];
        System.arraycopy(arr,0,tmp,0,2);
        //arraycopy 支持部分拷贝，而且1拷贝速度快
    }

    public static void main115(String[] args){

        int[] arr = {1,2,3,4};
        int[] tmp = new int[arr.length];
        tmp = Arrays.copyOfRange(arr,1,3);
        System.out.println(Arrays.toString(tmp));

        //左闭右开，指定范围拷贝
        //Java中from到to基本都是左闭右开
    }

    public static void main(String[] args) {
        int[] arr1 = {121,2,3,1};
        int[] arr2 = {1,22,4,6,3};
        arr2 = arr1.clone();
        System.out.println(Arrays.toString(arr2));
        //克隆，产生一个副本

    }
//    浅拷贝只复制指向某个对象的指针，
//    而不复制对象本身，新旧对象还是共
//    享同一块内存。 但深拷贝会另外创
//    造一个一模一样的对象，新对象跟原
//    对象不共享内存，修改新对象不会改
//     到原对象。
    //深拷贝 ：
    //浅拷贝 ：



    public static void main130(String[] args) {
        int[] arr1 = {121,2,3,1};
        int[] arr2 = {1,22,4,6,3};
        System.out.println(Arrays.equals(arr1, arr2));
        int[] arr3 = new int[10];
        Arrays.fill(arr3,-11);
        System.out.println(Arrays.toString(arr3));
        Arrays.fill(arr3,1,4,-111);
        System.out.println(Arrays.toString(arr3));

    }
//    shor
//    toString
//    fill
//    copyOf




}
//为什么Arrays类可以直接调用方法

class Person {
    String name;
    public static void play() {
        System.out.println("hehe");
    }
}